<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:pkg="http://expath.org/ns/pkg"
                xmlns:doc="http://www.oxygenxml.com/ns/doc/xsl"
                xmlns:gdata="http://fgeorges.org/ns/google/data"
                xmlns:atom="http://www.w3.org/2005/Atom"
                xmlns:os="http://a9.com/-/spec/opensearch/1.1/"
                xmlns:http="http://expath.org/ns/http-client"
                xmlns:impl="urn:X-FGeorges:xslt:google:data:impl"
                xmlns:x2x="TODO-xslt-to-xquery"
                x2x:target-ns="urn:X-FGeorges:xslt:google:data:impl"
                exclude-result-prefixes="#all"
                version="2.0">

   <xsl:import href="http://expath.org/ns/http-client.xsl"
               x2x:target-ns="http://expath.org/ns/http-client"/>
   <!--xsl:import href="gdata.xsl"
               x2x:target-ns="http://fgeorges.org/ns/google/data"/-->

   <!-- TODO: Should probably use a specific attribute for that purpose...? -->
   <pkg:import-uri>#none</pkg:import-uri>

   <doc:doc scope="stylesheet">
      <doc:desc>
         <doc:p><doc:b>Created on:</doc:b> Feb 1, 2009</doc:p>
         <doc:p><doc:b>Author:</doc:b> Florent Georges</doc:p>
         <doc:p>
            Private implementation module for gdata.
         </doc:p>
         <doc:p>
            Copyright (c) statement at the end of the file.
         </doc:p>
         <doc:p>
            See Google Data API documentation at
            <doc:a href="http://code.google.com/apis/gdata/"/>.
         </doc:p>
      </doc:desc>
   </doc:doc>


   <!-- ...........................................................................................
      Global parameters and variables.
   -->

   <doc:doc>
      <doc:desc>The name of this library, to send to Google for authentification.</doc:desc>
   </doc:doc>
   <xsl:variable name="impl:app-name" as="xs:string" select="'fgeorges-xsl-gdata-0.1'"/>


   <!-- ...........................................................................................
      Authentication.
   -->

   <doc:doc>
      <doc:desc>The URI to use to authenticate (via Client Login).</doc:desc>
   </doc:doc>
   <xsl:variable name="impl:auth-login-endpoint" as="xs:string" select="
       'https://www.google.com/accounts/ClientLogin'"/>

   <doc:doc>
      <doc:desc>The URI to use to authenticate via Auth Sub Request.</doc:desc>
   </doc:doc>
   <xsl:variable name="impl:auth-sub-request-endpoint" as="xs:string" select="
       'https://www.google.com/accounts/AuthSubRequest'"/>

   <doc:doc>
      <doc:desc>The URI to use to authenticate via Auth Sub Session Token.</doc:desc>
   </doc:doc>
   <xsl:variable name="impl:auth-sub-session-endpoint" as="xs:string" select="
       'https://www.google.com/accounts/AuthSubSessionToken'"/>

   <doc:doc>
      <doc:desc>The URI to use to authenticate via Auth Sub Revoke Token.</doc:desc>
   </doc:doc>
   <xsl:variable name="impl:auth-sub-revoke-endpoint" as="xs:string" select="
       'https://www.google.com/accounts/AuthSubRevokeToken'"/>

   <doc:doc>
      <doc:desc>The URI to use to authenticate via Auth Sub Token Info.</doc:desc>
   </doc:doc>
   <xsl:variable name="impl:auth-sub-info-endpoint" as="xs:string" select="
       'https://www.google.com/accounts/AuthSubTokenInfo'"/>


   <!-- ...........................................................................................
      Get feeds and entries.

      TODO: To remove.  Might be still used somewhere in g*.xsl...
   -->

   <!--
      TODO: To remove.  Might be still used somewhere in g*.xsl...
   -->
   <doc:doc>
      <doc:desc>TODO: Bla bla...</doc:desc>
      <doc:param name="service">TODO: Bla bla...</doc:param>
      <doc:param name="stuff-uri">TODO: Bla bla...</doc:param>
      <doc:param name="params">TODO: Bla bla...</doc:param>
      <doc:param name="since">TODO: Bla bla...</doc:param>
   </doc:doc>
   <xsl:function name="impl:get-stuff" as="element()?">
      <!-- the service element -->
      <xsl:param name="service"   as="element(gdata:service)"/>
      <!-- the feed URI -->
      <xsl:param name="stuff-uri" as="xs:string"/>
      <!-- query parameters -->
      <xsl:param name="params"    as="element(gdata:param)*"/>
      <!-- xs:date, xs:dateTime or xs:string (an ETag) -->
      <xsl:param name="since"     as="item()?"/>
      <!-- the URI, including encoded params -->
      <xsl:variable name="uri" as="xs:string" select="
          gdata:encode-params($stuff-uri, $params)"/>
      <!-- the HTTP request element -->
      <xsl:variable name="req" as="element(http:request)">
         <http:request method="get" href="{ $uri }">
            <!-- the GData protocol version, by default "2" -->
            <xsl:variable name="version" select="( $service/@gdata-version, '2.0')[1]"/>
            <http:header name="GData-Version" value="{ $version }"/>
            <http:header name="Authorization">
               <xsl:attribute name="value">
                  <xsl:choose>
                     <xsl:when test="$service/gdata:client-login">
                         <xsl:text>GoogleLogin auth=</xsl:text>
                         <xsl:value-of select="$service/gdata:client-login"/>
                     </xsl:when>
                     <xsl:when test="$service/gdata:auth-sub">
                         <xsl:text>AuthSub token="</xsl:text>
                         <xsl:value-of select="$service/gdata:auth-sub"/>
                         <xsl:text>"</xsl:text>
                     </xsl:when>
                     <xsl:otherwise>
                        <xsl:sequence select="gdata:error('GDATA009')"/>
                     </xsl:otherwise>
                  </xsl:choose>
               </xsl:attribute>
            </http:header>
            <xsl:sequence select="impl:make-since-header($since)"/>
         </http:request>
      </xsl:variable>
<xsl:message>
   REQUEST YO: <xsl:copy-of select="$req"/>
</xsl:message>
      <!-- send the request and get the response -->
      <xsl:variable name="resp" select="http:send-request($req)"/>
      <!-- does the response look ok? -->
      <xsl:if test="not(count($resp) = (1, 2))">
         <xsl:sequence select="gdata:error('GDATA004')"/>
      </xsl:if>
      <xsl:if test="exists($resp[2]) and not($resp[2] instance of document-node())">
         <xsl:sequence select="gdata:error('GDATA005', $resp[1]/http:body/@media-type)"/>
      </xsl:if>
      <xsl:if test="xs:integer($resp[1]/@status) ne 200">
         <xsl:sequence select="gdata:error('GDATA006', $resp[1]/@status, $resp[1]/@message)"/>
      </xsl:if>
      <xsl:sequence select="$resp[2]/*"/>
   </xsl:function>

   <!--
      TODO: To remove.  Might be still used somewhere in g*.xsl...
   -->
   <doc:doc>
      <doc:desc>TODO: Bla bla...</doc:desc>
      <doc:param name="service">TODO: Bla bla...</doc:param>
      <doc:param name="feed-uri">TODO: Bla bla...</doc:param>
      <doc:param name="start">TODO: Bla bla...</doc:param>
      <doc:param name="max">TODO: Bla bla...</doc:param>
      <doc:param name="params">TODO: Bla bla...</doc:param>
      <doc:param name="since">TODO: Bla bla...</doc:param>
   </doc:doc>
   <xsl:function name="impl:get-all-feeds" as="element(atom:feed)+">
      <!-- the service element -->
      <xsl:param name="service"  as="element(gdata:service)"/>
      <!-- the feed URI -->
      <xsl:param name="feed-uri" as="xs:string"/>
      <!-- start index -->
      <xsl:param name="start"    as="xs:integer"/>
      <!-- max results (must be also present with the same value in $params) -->
      <xsl:param name="max"      as="xs:integer"/>
      <!-- query parameters -->
      <xsl:param name="params"   as="element(gdata:param)*"/>
      <!-- start index as a gdata:param (can not be present in $params) -->
      <xsl:variable name="start-param" as="element(gdata:param)">
         <gdata:param name="start-index" value="{ $start }"/>
      </xsl:variable>
      <!-- one feed -->
      <xsl:variable name="this" select="
          gdata:get-feed($service, $feed-uri, ($params, $start-param))"/>
      <!-- index of the last enry in this feed -->
      <xsl:variable name="last" select="
          xs:integer($this/os:startIndex) + count($this/atom:entry) - 1"/>
      <!-- return this feed -->
      <xsl:sequence select="$this"/>
      <!-- recurse (or not) on following feeds -->
      <xsl:if test="$last lt xs:integer($this/os:totalResults)">
         <xsl:sequence select="
             impl:get-all-feeds($service, $feed-uri, $start + $max, $max, $params)"/>
      </xsl:if>
   </xsl:function>


   <!-- ...........................................................................................
      HTTP Since headers (use RFC 1123 dates).
   -->

   <doc:doc>
      <doc:desc>TODO: Bla bla...</doc:desc>
      <doc:param name="since">TODO: Bla bla...</doc:param>
   </doc:doc>
   <xsl:function name="impl:make-since-header" as="element(http:header)*">
      <!-- xs:date, xs:dateTime or xs:string (an ETag) -->
      <xsl:param name="since" as="item()?"/>
      <xsl:choose>
         <xsl:when test="empty($since)">
            <!-- nothing -->
         </xsl:when>
         <xsl:when test="$since instance of xs:dateTime">
            <http:header name="If-Modified-Since"
                         value="{ impl:format-datetime-rfc1123($since) }"/>
         </xsl:when>
         <xsl:when test="$since instance of xs:date">
            <http:header name="If-Modified-Since"
                         value="{ impl:format-date-rfc1123($since) }"/>
         </xsl:when>
         <xsl:when test="$since instance of xs:string">
            <http:header name="If-None-Match" value="{ $since }"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:sequence select="gdata:error('GDATA008')"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:function>

   <doc:doc>
      <doc:desc>TODO: Bla bla...</doc:desc>
      <doc:param name="date">TODO: Bla bla...</doc:param>
   </doc:doc>
   <xsl:function name="impl:format-date-rfc1123" as="xs:string">
      <xsl:param name="date" as="xs:date"/>
      <xsl:variable name="month-abbrevs" as="xs:string+" select="
          'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'"/>
      <!--xsl:sequence select="concat(
          format-date($date, '[D] '),
          $month-abbrevs[month-from-date($date)],
          format-date($date, ' [Y] 00:00:00 '),
          impl:format-zone(timezone-from-date($date))
        )"/-->
      <xsl:sequence select="concat(
          day-from-date($date),
          ' ',
          $month-abbrevs[month-from-date($date)],
          ' ',
          year-from-date($date),
          ' 00:00:00 ',
          impl:format-zone(timezone-from-date($date))
        )"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>TODO: Bla bla...</doc:desc>
      <doc:param name="dt">TODO: Bla bla...</doc:param>
   </doc:doc>
   <xsl:function name="impl:format-datetime-rfc1123" as="xs:string">
      <xsl:param name="dt" as="xs:dateTime"/>
      <xsl:variable name="month-abbrevs" as="xs:string+" select="
          'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'"/>
      <!--xsl:sequence select="concat(
          format-dateTime($dt, '[D] '),
          $month-abbrevs[month-from-dateTime($dt)],
          format-dateTime($dt, ' [Y] [H01]:[m]:[s] '),
          impl:format-zone(timezone-from-dateTime($dt))
        )"/-->
      <xsl:sequence select="concat(
          day-from-dateTime($dt),
          ' ',
          $month-abbrevs[month-from-dateTime($dt)],
          ' ',
          year-from-dateTime($dt),
          ' ',
          if ( hours-from-dateTime($dt) lt 10 ) then '0' else (),
          hours-from-dateTime($dt),
          ':',
          if ( minutes-from-dateTime($dt) lt 10 ) then '0' else (),
          minutes-from-dateTime($dt),
          ':',
          if ( seconds-from-dateTime($dt) lt 10 ) then '0' else (),
          seconds-from-dateTime($dt),
          ' ',
          impl:format-zone(timezone-from-dateTime($dt))
        )"/>
   </xsl:function>

   <doc:doc>
      <doc:desc>TODO: Bla bla...</doc:desc>
      <doc:param name="zone">TODO: Bla bla...</doc:param>
   </doc:doc>
   <xsl:function name="impl:format-zone" as="xs:string">
      <xsl:param name="zone" as="xs:dayTimeDuration?"/>
      <xsl:variable name="hour" select="hours-from-duration($zone)"/>
      <xsl:variable name="min" select="minutes-from-duration($zone)"/>
      <xsl:choose>
         <xsl:when test="empty($zone) or ($hour eq 0 and $min eq 0)">
            <xsl:sequence select="'Z'"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:sequence select="
                concat(if ( $hour lt 0 ) then '-' else '+',
                       if ( $hour lt 10 and $hour gt -10 ) then '0' else '',
                       string(abs($hour)),
                       if ( $min lt 10 and $min gt -10 ) then '0' else '',
                       string(abs($min)))"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:function>


   <!-- ...........................................................................................
      Copyright.
   -->

   <doc:doc scope="stylesheet">
      <doc:p>Copyright.</doc:p>
      <doc:pre>
Copyright (c) 2009 Florent Georges.

DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS COMMENT.

The contents of this file are subject to the Mozilla Public License
Version 1.0 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/.

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
the License for the specific language governing rights and limitations
under the License.

The Original Code is: all this file.

The Initial Developer of the Original Code is Florent Georges.

Contributor(s): none.
      </doc:pre>
   </doc:doc>

</xsl:stylesheet>
